package com.toft.widgets.workflow.service.impl;

import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.jbpm.api.JbpmException;
import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessDefinitionQuery;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.ProcessInstanceQuery;
import org.jbpm.api.history.HistoryProcessInstance;
import org.jbpm.api.history.HistoryTask;
import org.jbpm.api.task.Participation;
import org.jbpm.api.task.Task;
import org.jbpm.pvm.internal.history.model.HistoryTaskImpl;
import org.jbpm.pvm.internal.model.ActivityImpl;
import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
import org.jbpm.pvm.internal.model.TransitionImpl;
import org.jbpm.pvm.internal.svc.TaskServiceImpl;
import org.jbpm.pvm.internal.task.ParticipationImpl;
import org.jbpm.pvm.internal.task.TaskDefinitionImpl;
import org.jbpm.pvm.internal.task.TaskImpl;
import org.jbpm.pvm.internal.wire.WireContext;
import org.jbpm.pvm.internal.wire.descriptor.ObjectDescriptor;
import org.jbpm.pvm.internal.wire.descriptor.StringDescriptor;
import org.jbpm.pvm.internal.wire.operation.FieldOperation;
import org.jbpm.pvm.internal.wire.usercode.UserCodeReference;

import com.toft.widgets.workflow.adpater.WorkflowQueryAdapter;
import com.toft.widgets.workflow.dao.HibernateDao;
import com.toft.widgets.workflow.model.ActivityStatus;
import com.toft.widgets.workflow.model.Page;
import com.toft.widgets.workflow.model.ProcessActivity;
import com.toft.widgets.workflow.model.ProcessHistoryInfo;
import com.toft.widgets.workflow.model.TaskItem;
import com.toft.widgets.workflow.model.TransitionInfo;
import com.toft.widgets.workflow.model.WorkflowUser;
import com.toft.widgets.workflow.service.IWorkflowQueryService;
import com.toft.widgets.workflow.service.JbpmServiceSupport;
import com.toft.widgets.workflow.service.WorkflowFacade;
import com.toft.widgets.workflow.utils.ConstantUtil;
import com.toft.widgets.workflow.utils.DateConvertUtil;
import com.toft.widgets.workflow.utils.ReflectionUtils;
import com.toft.widgets.workflow.utils.TableConstants;

/**
 * 查询服务接口实现类
 * 
 * @author 邹庆林
 * @version 1.0
 */

public class WorkflowQueryServiceImpl extends JbpmServiceSupport implements IWorkflowQueryService {

	protected static Logger logger = Logger.getLogger(WorkflowQueryServiceImpl.class.getName());

	public ProcessDefinition findProcessDefintionById(String processDefinitionId) {

		if (null == processDefinitionId || "".equals(processDefinitionId)) {
			throw new JbpmException("无效的查询条件processDefinitionId!");
		}

		ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();

		ProcessDefinition processDefinition = processDefinitionQuery.processDefinitionId(processDefinitionId).uniqueResult();

		return processDefinition;

	}

	public ProcessInstance findProcessInstanceById(String processInstanceId) {

		if (null == processInstanceId || "".equals(processInstanceId)) {
			throw new JbpmException("无效的查询条件processDefinitionId!");
		}

		ProcessInstanceQuery processInstanceQuery = executionService.createProcessInstanceQuery();

		ProcessInstance processInstance = processInstanceQuery.processInstanceId(processInstanceId).uniqueResult();

		return processInstance;

	}

	public List searchProcessInstances(TaskItem taskItem) {
		List list = new ArrayList();
		try {
			Criteria criteria = WorkflowFacade.getSession().createCriteria(TaskImpl.class);
			getProcessInstanceByTaskItem(taskItem, criteria);
			list = criteria.list();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}

	public Page searchProcessInstances(TaskItem taskItem, Page page) {
		try {
			Criteria criteria = WorkflowFacade.getSession().createCriteria(TaskImpl.class);
			getProcessInstanceByTaskItem(taskItem, criteria);
			page.setAutoCount(false);
			page.setTotalCount(criteria.list().size());
			page = HibernateDao.findPage(page, criteria);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return page;
	}

	private void getProcessInstanceByTaskItem(TaskItem taskItem, Criteria criteria) {
		criteria.createAlias("processInstance", "processInstance");
		criteria.createAlias("historyProcessInstance", "historyProcessInstance");

		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(Projections.groupProperty("businessType").as("businessType"));
		projectionList.add(Projections.groupProperty("businessName").as("businessName"));
		projectionList.add(Projections.groupProperty("businessSN").as("businessSN"));
		projectionList.add(Projections.groupProperty("businessMoney").as("businessMoney"));
		projectionList.add(Projections.groupProperty("historyProcessInstance.startTime").as("createTime"));
		projectionList.add(Projections.groupProperty("processInstance.state").as("state"));
		projectionList.add(Projections.groupProperty("exeId").as("processInstanceId"));
		projectionList.add(Projections.groupProperty("agencyId").as("agencyId"));
		projectionList.add(Projections.groupProperty("departmentId").as("departmentId"));
		projectionList.add(Projections.groupProperty("applicationUser").as("submitUser"));
		// projectionList.add(Projections.groupProperty("workflowObject").as("workflowObject"));
		getCriteriaByHistoryTaskItem(taskItem, criteria);
		criteria.setProjection(projectionList);

		criteria.addOrder(Order.desc("createTime"));

		criteria.setResultTransformer(Transformers.aliasToBean(TaskItem.class));
	}

	private ProjectionList getHistoryTaskProjectionList() {
		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(Projections.groupProperty("name").as("activityName"));
		projectionList.add(Projections.groupProperty("businessRecordId").as("businessRecordId"));
		projectionList.add(Projections.groupProperty("businessType").as("businessType"));
		projectionList.add(Projections.groupProperty("businessName").as("businessName"));
		projectionList.add(Projections.groupProperty("businessSN").as("businessSN"));
		projectionList.add(Projections.groupProperty("businessMoney").as("businessMoney"));
		projectionList.add(Projections.groupProperty("historyProcessInstance.startTime").as("createTime"));
		projectionList.add(Projections.max("endTime").as("endTime"));
		projectionList.add(Projections.groupProperty("historyProcessInstance.state").as("state"));
		projectionList.add(Projections.groupProperty("url").as("url"));
		projectionList.add(Projections.groupProperty("exeId").as("processInstanceId"));
		projectionList.add(Projections.groupProperty("agencyId").as("agencyId"));
		projectionList.add(Projections.groupProperty("departmentId").as("departmentId"));
		projectionList.add(Projections.groupProperty("applicationUser").as("submitUser"));
		// projectionList.add(Projections.property("workflowObject").as("workflowObject"));
		return projectionList;
	}

	public Page findHistoryTasks(String userCode, TaskItem taskItem, Page page) {
		if (null == userCode || "".equals(userCode)) {
			throw new JbpmException("无效的用户标识!");
		}

		try {
			Criteria criteria = WorkflowFacade.getSession().createCriteria(HistoryTaskImpl.class);
			criteria.createAlias("historyProcessInstance", "historyProcessInstance");
			ProjectionList projectionList = getHistoryTaskProjectionList();
			criteria.setProjection(projectionList);
			criteria.add(Restrictions.eq("assignee", userCode));
			criteria.add(Restrictions.sqlRestriction("{alias}.STATE_='" + Task.STATE_COMPLETED + "'"));
			criteria.add(Restrictions.isNull("abnormal"));
			getCriteriaByHistoryTaskItem(taskItem, criteria);
			page.setAutoCount(false);
			page.setTotalCount(criteria.list().size());
			criteria.addOrder(Order.desc("endTime"));
			criteria.setResultTransformer(Transformers.aliasToBean(TaskItem.class));
			page = HibernateDao.findPage(page, criteria);
		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("查询个人已办任务时异常!");
		} finally {
		}
		return page;
	}

	public List findHistoryTasks(TaskItem taskItem) {

		List list = new ArrayList();
		try {
			Criteria criteria = WorkflowFacade.getSession().createCriteria(HistoryTaskImpl.class);
			criteria.createAlias("historyProcessInstance", "historyProcessInstance");
			ProjectionList projectionList = getHistoryTaskProjectionList();
			criteria.setProjection(projectionList);
			if (StringUtils.isNotEmpty(taskItem.getAssignee())) {
				criteria.add(Restrictions.eq("assignee", taskItem.getAssignee()));
			}
			criteria.add(Restrictions.sqlRestriction("{alias}.STATE_='" + Task.STATE_COMPLETED + "'"));
			criteria.add(Restrictions.isNull("abnormal"));
			getCriteriaByHistoryTaskItem(taskItem, criteria);

			criteria.addOrder(Order.desc("createTime"));
			criteria.setResultTransformer(Transformers.aliasToBean(TaskItem.class));
			list = criteria.list();
		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("查询个人已办任务时异常!");
		}
		return list;
	}

	private void getCriteriaByHistoryTaskItem(TaskItem taskItem, Criteria criteria) {
		if (null != taskItem) {
			String businessRecordId = taskItem.getBusinessRecordId();
			String businessType = taskItem.getBusinessType();  
			String businessSN = taskItem.getBusinessSN();
			String processInstanceId = taskItem.getProcessInstanceId();
			String agencyId = taskItem.getAgencyId();
			String departmentId = taskItem.getDepartmentId();
			String businessMoney = taskItem.getBusinessMoney();
			Date startDateTime = taskItem.getCreateTime();
			Date endDateTime = taskItem.getEndTime();
			if (StringUtils.isNotEmpty(businessRecordId)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.BUSINESSRECORDID_=?", businessRecordId, Hibernate.STRING));
			}
			if (StringUtils.isNotEmpty(businessType)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.BUSINESSTYPE_=?", businessType, Hibernate.STRING));
			}
			if (StringUtils.isNotEmpty(businessSN)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.BUSINESSSN_ like ?", "%" + businessSN + "%", Hibernate.STRING));
			}
			if (StringUtils.isNotEmpty(processInstanceId)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.EXEID_=?", processInstanceId, Hibernate.STRING));
			}
			if (StringUtils.isNotEmpty(agencyId)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.AGENCYID_=?", agencyId, Hibernate.STRING));
			}
			if (StringUtils.isNotEmpty(departmentId)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.DEPARTMENTID_ like ?", "%" + departmentId + "%", Hibernate.STRING));
			}
			if (StringUtils.isNotEmpty(businessMoney)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.BUSINESSMONEY_ like ?", "%" + businessMoney + "%", Hibernate.STRING));
			}
			if (startDateTime != null) {
				criteria.add(Restrictions.sqlRestriction("{alias}.CREATE_ >= ?", startDateTime, Hibernate.TIMESTAMP));
				}
				if (endDateTime != null) {
				criteria.add(Restrictions.sqlRestriction("{alias}.CREATE_ <= ?", endDateTime, Hibernate.TIMESTAMP));
				}

		}
	}

	private ProjectionList getTaskProjectionList() {
		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(Projections.property("dbid").as("id"));
		projectionList.add(Projections.property("activityName").as("activityName"));
		projectionList.add(Projections.property("businessRecordId").as("businessRecordId"));
		projectionList.add(Projections.property("businessType").as("businessType"));
		projectionList.add(Projections.property("businessName").as("businessName"));
		projectionList.add(Projections.property("businessSN").as("businessSN"));
		projectionList.add(Projections.property("businessMoney").as("businessMoney"));
		projectionList.add(Projections.property("createTime").as("createTime"));
		projectionList.add(Projections.property("url").as("url"));
		projectionList.add(Projections.property("state").as("state"));
		projectionList.add(Projections.property("exeId").as("processInstanceId"));
		projectionList.add(Projections.property("agencyId").as("agencyId"));
		projectionList.add(Projections.property("departmentId").as("departmentId"));
		projectionList.add(Projections.property("applicationUser").as("submitUser"));
		projectionList.add(Projections.property("workflowObject").as("workflowObject"));
		projectionList.add(Projections.property("assignee").as("assignee"));
		projectionList.add(Projections.property("submitActivity").as("submitActivity"));
		return projectionList;
	}

	public List findPersonalTaskForWaiting(String userCode, TaskItem taskItem) {
		if (null == userCode || "".equals(userCode)) {
			throw new JbpmException("无效的用户标识!");
		}

		List personalTasks = new ArrayList();
		try {
			Criteria criteria = WorkflowFacade.getSession().createCriteria(TaskImpl.class);
			ProjectionList projectionList = getTaskProjectionList();
			criteria.setProjection(projectionList);
			criteria.add(Restrictions.sqlRestriction("{alias}.STATE_<>?", Task.STATE_SUSPENDED, Hibernate.STRING));

			Disjunction disjunction2 = Restrictions.disjunction();
			disjunction2.add(Restrictions.sqlRestriction("{alias}.ASSIGNEE_=?", userCode, Hibernate.STRING));
			disjunction2.add(Restrictions.like("agentId", "%" + userCode + "%"));
			criteria.add(disjunction2);
			getCriteriaByTaskItem(taskItem, criteria);
			criteria.addOrder(Order.desc("priority"));
			criteria.addOrder(Order.desc("createTime"));
			criteria.setResultTransformer(Transformers.aliasToBean(TaskItem.class));
			personalTasks = criteria.list();

		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("查询个人待办任务时异常!");
		} finally {
		}
		return personalTasks;
	}

	private void getCriteriaByTaskItem(TaskItem taskItem, Criteria criteria) {
		if (null != taskItem) {
			String businessRecordId = taskItem.getBusinessRecordId();
			String businessType = taskItem.getBusinessType();
			String businessSN = taskItem.getBusinessSN();
			String processInstanceId = taskItem.getProcessInstanceId();
			String agencyId = taskItem.getAgencyId();
			String departmentId = taskItem.getDepartmentId();
			String businessMoney = taskItem.getBusinessMoney();

			boolean isRefuseToSubmitActivity = taskItem.isRefuseToSubmitActivity();
			if (StringUtils.isNotEmpty(businessRecordId)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.BUSINESSRECORDID_=?", businessRecordId, Hibernate.STRING));
			}
			if (StringUtils.isNotEmpty(businessType)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.BUSINESSTYPE_=?", businessType, Hibernate.STRING));
			}
			if (StringUtils.isNotEmpty(businessSN)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.BUSINESSSN_ like ?", "%" + businessSN + "%", Hibernate.STRING));
			}
			if (StringUtils.isNotEmpty(processInstanceId)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.EXEID_=?", processInstanceId, Hibernate.STRING));
			}
			if (isRefuseToSubmitActivity) {
				criteria.add(Restrictions.sqlRestriction("{alias}.SUBMITACTIVITY_ = ?", ConstantUtil.REFUSE_TO_SUBMITACTIVITY, Hibernate.STRING));
			} else {
				criteria.add(Restrictions.sqlRestriction("{alias}.SUBMITACTIVITY_ is null"));
			}
			if (StringUtils.isNotEmpty(agencyId)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.AGENCYID_=?", agencyId, Hibernate.STRING));
			}
			if (StringUtils.isNotEmpty(departmentId)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.DEPARTMENTID_ like ?", "%" + departmentId + "%", Hibernate.STRING));
			}
			if (StringUtils.isNotEmpty(businessMoney)) {
				criteria.add(Restrictions.sqlRestriction("{alias}.BUSINESSMONEY_ like ?", "%" + businessMoney + "%", Hibernate.STRING));
			}
		}
	}

	public List findPersonalTaskForWaiting(String userCode) {
		return findPersonalTaskForWaiting(userCode, null);
	}

	public List findGroupTaskForWaiting(WorkflowUser userInfo, TaskItem taskItem) {
		if (null == userInfo || StringUtils.isEmpty(userInfo.getCode())) {
			throw new JbpmException("无效的用户标识!");
		}
		List groupTasks = new ArrayList();
		List deptList = new ArrayList();
		try {
			// 从扩展属性中取出部门ID
			if (null != userInfo.getAttributes()) {
				deptList = (List) userInfo.getAttributes().get("DEPID");
				for (Iterator iter = deptList.iterator(); iter.hasNext();) {
					Map map = (Map) iter.next();
					String jobId = (String) map.get("JOBID");
					String departmentId = (String) map.get("DEPID");
					userInfo.setDepartmentId(departmentId);
					List list = new ArrayList();
					list.add(jobId);
					groupTasks.addAll(getGroupTaskList(userInfo, list, taskItem));
				}

			}
			if (deptList.size() == 0) {
				Map conditions = new HashMap();
				conditions.put("code", userInfo.getCode());
				conditions.put("conn", WorkflowFacade.getConnection());

				// 根据条件获取用户所在的组ID(与参与者规则关联查询)
				List groupIdsList = WorkflowQueryAdapter.getInstance().getGroupIdsByUserCode(conditions);
				if (groupIdsList.size() > 0) {
					groupTasks = getGroupTaskList(userInfo, groupIdsList, taskItem);
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("获取用户的组任务错误!" + e);
		} finally {
		}

		return groupTasks;
	}

	// 获取用户的组任务
	public List findGroupTaskForWaiting(WorkflowUser userInfo) {
		return findGroupTaskForWaiting(userInfo, null);
	}

	private List getGroupTaskList(WorkflowUser userInfo, List groupIdsList, TaskItem taskItem) {
		// 用hibernate通用方法查询 解决DB2查询不兼容问题 by liangleilei on 2010-8-23
		Criteria criteria = WorkflowFacade.getSession().createCriteria(TaskImpl.class);
		criteria.createAlias("participations", "participations");
		ProjectionList projectionList = getTaskProjectionList();
		projectionList.add(Projections.property("participations.groupId").as("groupId"));
		criteria.setProjection(projectionList);
		// 获取机构ID
		String agencyId = userInfo.getAgencyId();
		// 获取部门ID
		String departmentId = userInfo.getDepartmentId();
		// 机构ID和部门ID都不为空
		if (StringUtils.isNotEmpty(agencyId) && StringUtils.isNotEmpty(departmentId)) {
			criteria.add(Restrictions.eq(ConstantUtil.AGENCY_ID, agencyId));
			criteria.add(Restrictions.eq(ConstantUtil.DEPARTMENT_ID, departmentId));
		}
		getCriteriaByTaskItem(taskItem, criteria);
		criteria.add(Restrictions.sqlRestriction("{alias}.STATE_<>?", Task.STATE_SUSPENDED, Hibernate.STRING));
		criteria.add(Restrictions.eq("participations.state", "1"));
		criteria.add(Restrictions.eq("participations.type", "candidate"));
		criteria.add(Restrictions.in("participations.groupId", groupIdsList));
		criteria.addOrder(Order.desc("priority"));
		criteria.addOrder(Order.desc("createTime"));
		criteria.setResultTransformer(Transformers.aliasToBean(TaskItem.class));
		return criteria.list();
	}

	public Page findAllTaskList(String userCode, TaskItem taskItem, Page page) {
		try {

			if (StringUtils.isEmpty(userCode)) {
				throw new JbpmException("无效的用户标识!");
			}

			Criteria criteria = WorkflowFacade.getSession().createCriteria(TaskImpl.class);
			criteria.createAlias("participations", "participations", CriteriaSpecification.LEFT_JOIN);
			ProjectionList projectionList = getTaskProjectionList();
			criteria.add(Restrictions.sqlRestriction("{alias}.STATE_<>?", Task.STATE_SUSPENDED, Hibernate.STRING));

			Disjunction disjunction = Restrictions.disjunction();

			Map conditions = new HashMap();
			conditions.put("code", userCode);
			conditions.put("conn", WorkflowFacade.getConnection());

			// 根据条件获取用户所在的组ID(与参与者规则关联查询)
			List groupIdsList = WorkflowQueryAdapter.getInstance().getGroupIdsByUserCode(conditions);
			if (groupIdsList.size() > 0) {
				projectionList.add(Projections.property("participations.groupId").as("groupId"));
				Conjunction conjunction = Restrictions.conjunction();
				conjunction.add(Restrictions.eq("participations.state", "1"));
				conjunction.add(Restrictions.eq("participations.type", "candidate"));
				conjunction.add(Restrictions.in("participations.groupId", groupIdsList));
				disjunction.add(conjunction);
			}
			if (taskItem.getCreateTime() != null) {
				criteria.add(Restrictions.sqlRestriction("{alias}.CREATE_ >= ?", taskItem.getCreateTime(), Hibernate.TIMESTAMP));
				}
				if (taskItem.getEndTime() != null) {
				criteria.add(Restrictions.sqlRestriction("{alias}.CREATE_ <= ?", taskItem.getEndTime(), Hibernate.TIMESTAMP));
				}
			disjunction.add(Restrictions.sqlRestriction("{alias}.ASSIGNEE_=?", userCode, Hibernate.STRING));
			disjunction.add(Restrictions.like("agentId", "%" + userCode + "%"));
			criteria.add(disjunction);
			criteria.setProjection(projectionList);
			getCriteriaByTaskItem(taskItem, criteria);
			criteria.addOrder(Order.desc("priority"));
			criteria.addOrder(Order.desc("createTime"));
			criteria.setResultTransformer(Transformers.aliasToBean(TaskItem.class));
			page = HibernateDao.findPage(page, criteria);

		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("查询待办任务时异常!");
		} finally {
		}
		return page;
	}

	public List findTaskListByProcessInstanceId(String processInstanceId) {
		List list = new ArrayList();
		try {
			Criteria criteria = WorkflowFacade.getSession().createCriteria(TaskImpl.class);
			criteria.createAlias("participations", "participations", CriteriaSpecification.LEFT_JOIN);
			ProjectionList projectionList = getTaskProjectionList();
			projectionList.add(Projections.property("participations.groupId").as("groupId"));
			criteria.setProjection(projectionList);
			criteria.add(Restrictions.sqlRestriction("{alias}.STATE_<>'" + Task.STATE_SUSPENDED + "'"));

			criteria.add(Restrictions.ne("taskType", ConstantUtil.COUNTERSIGNATURE_TASK_PARENT));
			criteria.add(Restrictions.eq("exeId", processInstanceId));
			criteria.addOrder(Order.desc("priority"));
			criteria.addOrder(Order.desc("createTime"));
			criteria.setResultTransformer(Transformers.aliasToBean(TaskItem.class));
			list = criteria.list();
		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("查询待办任务时异常!");
		}
		return list;

	}

	public List findTaskListByProcessInstanceId(TaskItem taskItem) {
		List list = new ArrayList();
		try {
			Criteria criteria = WorkflowFacade.getSession().createCriteria(TaskImpl.class);
			ProjectionList projectionList = getTaskProjectionList();
			criteria.setProjection(projectionList);
			criteria.add(Restrictions.sqlRestriction("{alias}.STATE_<>'" + Task.STATE_SUSPENDED + "'"));
			getCriteriaByTaskItem(taskItem, criteria);
			criteria.setResultTransformer(Transformers.aliasToBean(TaskItem.class));
			list = criteria.list();
		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("查询待办任务时异常!");
		} finally {
		}
		return list;

	}

	public Task getTask(String taskId) {
		if (null == taskId && "".equals(taskId)) {
			throw new JbpmException("无效的任务标识!");
		}
		TaskServiceImpl taskServiceImpl = (TaskServiceImpl) taskService;
		TaskImpl task = (TaskImpl) taskServiceImpl.getTask(taskId);
		return task;
	}

	public List getOutgoingTransitionsByTaskId(String taskId) {
		if (StringUtils.isEmpty(taskId)) {
			throw new JbpmException("无效的任务标识!");
		}
		TaskImpl task = (TaskImpl) taskService.getTask(taskId);
		TaskImpl superTask = task.getSuperTask();
		if (null != task.getSuperTask()) {
			task = superTask;
		}
		ProcessDefinitionImpl pd = (ProcessDefinitionImpl) task.getProcessInstance().getProcessDefinition();
		ActivityImpl activityFind = pd.findActivity(task.getName());
		if (activityFind != null) {
			return activityFind.getOutgoingTransitions();
		}
		return null;
	}

	public List getIncomingTransitionsByTaskId(String taskId) {
		if (StringUtils.isEmpty(taskId)) {
			throw new JbpmException("无效的任务标识!");
		}
		TaskImpl task = (TaskImpl) taskService.getTask(taskId);
		TaskImpl superTask = task.getSuperTask();
		if (null != task.getSuperTask()) {
			task = superTask;
		}
		ProcessDefinitionImpl pd = (ProcessDefinitionImpl) task.getProcessInstance().getProcessDefinition();
		ActivityImpl activityFind = pd.findActivity(task.getName());
		if (activityFind != null) {
			return activityFind.getIncomingTransitions();
		}
		return null;
	}

	public List getTaskTransitions(String taskId) {

		if (null == taskId && "".equals(taskId)) {
			throw new JbpmException("无效的任务标识!");
		}

		List transitions = new ArrayList();
		List result = new ArrayList();
		Session session = WorkflowFacade.getSession();
		try {
			TaskImpl task = (TaskImpl) session.get(TaskImpl.class, new Long(taskId));
			if (null != task.getSuperTask()) {
				transitions = taskService.getOutcomesDup(task.getSuperTask().getId());
			} else {
				transitions = taskService.getOutcomesDup(taskId);
			}

			for (Iterator iter = transitions.iterator(); iter.hasNext();) {
				TransitionImpl transition = (TransitionImpl) iter.next();
				TransitionInfo transitionInfo = new TransitionInfo();
				BeanUtils.copyProperties(transitionInfo, transition);
				result.add(transitionInfo);
				if ("completed".equals(transition.getName())) {
					iter.remove();
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("获取任务流向时异常!" + e);
		} finally {
		}

		return result;
	}

	// 通过任务获取变量
	public Map getTaskVariable(String taskId) {

		if (null == taskId && "".equals(taskId)) {
			throw new JbpmException("无效的任务标识!");
		}
		Map variables = new HashMap();
		TaskServiceImpl taskServiceImpl = (TaskServiceImpl) taskService;
		Session session = WorkflowFacade.getSession();
		try {
			TaskImpl task = (TaskImpl) session.get(TaskImpl.class, new Long(taskId));
			String taskDbId = String.valueOf(task.getDbid());
			Set variableNames = taskServiceImpl.getVariableNames(taskDbId);
			variables = taskServiceImpl.getVariables(taskDbId, variableNames);
		} catch (Exception e) {
			throw new JbpmException("通过任务获取变量时异常!" + e);
		} finally {

		}

		return variables;
	}

	public List searchDynamicTasks(String taskId) {

		if (null == taskId || "".equals(taskId)) {
			throw new JbpmException("无效的任务标识！");
		}

		TaskServiceImpl taskServiceImpl = (TaskServiceImpl) taskService;

		return taskServiceImpl.getSubTasks(taskId);

	}

	public String getProcessInstanceState(String processInstanceId) {

		if (null == processInstanceId || "".equals(processInstanceId)) {
			throw new JbpmException("无效的流程实例标识! " + processInstanceId);
		}
		HistoryProcessInstance historyProcessInstance = historyService.createHistoryProcessInstanceQuery().processInstanceId(processInstanceId).uniqueResult();
		if (null != historyProcessInstance) {
			return historyProcessInstance.getState();
		}

		return "";
	}

	public String getProcessDefinitionState(String processDefinitionId) {

		if (null == processDefinitionId || "".equals(processDefinitionId)) {
			throw new JbpmException("无效的流程定义标识!" + processDefinitionId);
		}

		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).uniqueResult();

		if (processDefinition.isSuspended()) {
			return "suspended";
		}

		return "active";
	}

	// TODO
	public Object viewProcessInfoDuplication(String processInstanceId) {

		if (null == processInstanceId || "".equals(processInstanceId)) {
			throw new JbpmException("查看流程的流程实例标识不正确! " + processInstanceId);
		}

		List processActivitys = new ArrayList();
		ProcessActivity processActivity = null;

		String sql = "select historytas2_.ASSIGNEE_ as assignee,historytas2_.AGENTID_ as agentId,this_.EXECUTION_ as executionId,this_.ACTIVITY_NAME_ as activityName,(case when this_.TRANSITION_ is null  then historytas2_.outcome_  else this_.TRANSITION_ end) as transitionName,this_.START_ as startTime,this_.END_ as endTime,details3_.MESSAGE_ as message"
				+ " from "
				+ TableConstants.JBPM4_HIST_ACTINST
				+ " this_ "
				+ " inner join "
				+ TableConstants.JBPM4_HIST_PROCINST
				+ " historypro1_ on  this_.HPROCI_=historypro1_.DBID_ "
				+ " left join "
				+ TableConstants.JBPM4_HIST_TASK
				+ " historytas2_ on (this_.HTASK_=historytas2_.PARENTID_  or this_.HTASK_=historytas2_.DBID_) and historytas2_.assignee_ is not null "
				+ " left join "
				+ TableConstants.JBPM4_HIST_DETAIL
				+ " details3_  on historytas2_.DBID_=details3_.HTASK_ "
				+ " where historypro1_.ID_='"
				+ processInstanceId + "' and this_.END_  is not null";
		logger.info(sql);
		SQLQuery query = WorkflowFacade.getSession().createSQLQuery(sql);
		query.addScalar("assignee", Hibernate.STRING);
		query.addScalar("agentId", Hibernate.STRING);
		query.addScalar("executionId", Hibernate.STRING);
		query.addScalar("activityName", Hibernate.STRING);
		query.addScalar("transitionName", Hibernate.STRING);
		query.addScalar("startTime", Hibernate.TIMESTAMP);
		query.addScalar("endTime", Hibernate.TIMESTAMP);
		query.addScalar("message", Hibernate.STRING);
		query.setResultTransformer(Transformers.aliasToBean(ProcessHistoryInfo.class));
		List historyActivityInstances = query.list();

		if (null != historyActivityInstances && historyActivityInstances.size() > 0) {
			for (Iterator iter = historyActivityInstances.iterator(); iter.hasNext();) {
				ProcessHistoryInfo processHistoryInfo = (ProcessHistoryInfo) iter.next();
				processActivity = copyProcessHistoryInfoToProcessActivity(processHistoryInfo);
				String transition = "";
				if (processHistoryInfo.getExecutionId().indexOf(".transition") != -1) {
					transition = processHistoryInfo.getExecutionId().substring(processHistoryInfo.getExecutionId().indexOf(".transition"));
					if (transition.split("\\.").length > 1) {
						transition = StringUtils.substringBetween(transition, ".");
					}
				}
				processActivity.setTransition("".equals(transition) ? processHistoryInfo.getTransitionName() + "," : processHistoryInfo.getTransitionName()
						+ "," + transition);
				processActivitys.add(processActivity);

			}
		}
		// 当前处于活动状态的任务节点
		sql = "select h.activity_name_ as activityName,h.start_ as createTime,t.exeid_ as processInstanceId,t.dbid_ as id " + "from "
				+ TableConstants.JBPM4_HIST_ACTINST + " h " + " left join " + TableConstants.JBPM4_TASK
				+ " t on (h.htask_=t.dbid_ or h.htask_ is null or h.htask_ = t.supertask_) "
				+ "where h.end_ is NULL and instr(h.execution_,t.exeid_)>0 and t.tasktype_<>'" + ConstantUtil.COUNTERSIGNATURE_TASK_PARENT + "' and t.exeid_='"
				+ processInstanceId + "'";
		logger.info(sql);
		query = WorkflowFacade.getSession().createSQLQuery(sql);
		query.addScalar("id", Hibernate.LONG);
		query.addScalar("activityName", Hibernate.STRING);
		query.addScalar("createTime", Hibernate.TIMESTAMP);
		query.addScalar("processInstanceId", Hibernate.STRING);
		query.setResultTransformer(Transformers.aliasToBean(TaskItem.class));
		List activityInstances = query.list();

		for (Iterator iter = activityInstances.iterator(); iter.hasNext();) {
			TaskItem taskItem = (TaskItem) iter.next();
			processActivity = new ProcessActivity();
			processActivity.setActivityStatus(ActivityStatus.PROCESSING);
			processActivity.setActivityType(taskItem.getActivityName());
			processActivity.setCreateTime(DateConvertUtil.dateToString(taskItem.getCreateTime()));
			TransitionImpl transitionImpl = (TransitionImpl) getIncomingTransitionsByTaskId(taskItem.getId()).get(0);
			processActivity.setTransition(transitionImpl.getName());
			List userList = getNextOperatorsListByTaskId(taskItem.getId());
			String taskExecutor = ReflectionUtils.convertElementPropertyToString(userList, "NAME", ",");
			processActivity.setTaskExecutor(taskExecutor);
			processActivitys.add(processActivity);

		}

		return processActivitys;
	}

	private ProcessActivity copyProcessHistoryInfoToProcessActivity(ProcessHistoryInfo processHistoryInfo) {
		ProcessActivity processActivity = new ProcessActivity();
		processActivity.setActivityStatus(ActivityStatus.PROCESSED);
		processActivity.setActivityType(processHistoryInfo.getActivityName());
		Date startTime = processHistoryInfo.getStartTime();
		Date endTime = processHistoryInfo.getEndTime();
		String agentId = processHistoryInfo.getAgentId();
		String assignee = processHistoryInfo.getAssignee();
		String commentType = processHistoryInfo.getCommentType();
		String commentContent = processHistoryInfo.getCommentContent();
		if (null != startTime) {
			processActivity.setCreateTime(DateConvertUtil.dateToString(startTime));
		}
		if (null != endTime) {
			processActivity.setEndTime(DateConvertUtil.dateToString(endTime));
		}
		if (StringUtils.isNotEmpty(agentId)) {
			processActivity.setTaskAgent(processHistoryInfo.getAgentIdName()); // 任务代理人
		}
		if (StringUtils.isNotEmpty(assignee)) {
			processActivity.setTaskExecutor(processHistoryInfo.getAssigneeName()); // 任务处理人
		}
		if (StringUtils.isNotEmpty(commentType)) {
			processActivity.setTaskCommentType(commentType);
		}
		if (StringUtils.isNotEmpty(commentContent)) {
			processActivity.setTaskCommentConent(StringEscapeUtils.unescapeHtml(commentContent));
		}
		return processActivity;
	}

	public String getProcessInstanceStateByTaskId(String taskId) {

		if (null == taskId || "".equals(taskId)) {
			throw new JbpmException("获取流程实例状态时，任务标识不正确!" + taskId);
		}

		String processInstanceId = "";

		try {
			HistoryTask historyTask = (HistoryTask) WorkflowFacade.getSession().load(HistoryTaskImpl.class, new Long(taskId));

			if (null != historyTask) {
				processInstanceId = historyTask.getExecutionId();
			}

			if (!"".equals(processInstanceId)) {
				if (processInstanceId.indexOf("transition") != -1) {
					processInstanceId = processInstanceId.substring(0, processInstanceId.lastIndexOf("."));
				}
			}

			HistoryProcessInstance historyProcessInstance = historyService.createHistoryProcessInstanceQuery().processInstanceId(processInstanceId)
					.uniqueResult();
			if (null != historyProcessInstance) {
				return historyProcessInstance.getState();
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("获取流程实例状态时错误,请重试");
		}
		return "";
	}

	public boolean isEndedByProcessInstanceId(String processInstanceId) {
		ProcessInstance processInstance = executionService.createProcessInstanceQuery().processInstanceId(processInstanceId).uniqueResult();
		if (processInstance == null) {
			return true;
		}
		return processInstance.isEnded();
	}

	/*
	 * 完成提交节点（即普通任务节点） 如果提交节点是第一次创建，就自动完成， 否则就不自动完成，需要提交人手动完成任务
	 */
	public List completeSubmitActivity(String processInstanceId, String userCode) {

		String taskId = "";

		if (null != processInstanceId && !"".equals(processInstanceId)) {
			TaskImpl task = (TaskImpl) taskService.createTaskQuery().processInstanceId(processInstanceId).uniqueResult();
			if (null != task) {
				taskId = task.getId();
				if (null != task.getSubmitActivity() && task.getSubmitActivity().equals(ConstantUtil.SUBMIT_ACTIVITY)) { // 是提交节点
					if (null != task.getAssignee() && task.getAssignee().equals(userCode)) { // 提交节点参与者为系统当前登录用户
						if (null == taskService.getVariable(task.getId(), ConstantUtil.TASK_COMMNET_TYPE_REFUSE)) { // 提交节点是第一次创建，不是被退回的，就要自动完成
							// 获取流程走向
							String transition = getTaskTransition(task.getId(), ConstantUtil.APPROVE_OPERATION_PASS);
							// 完成任务
							taskService.completeTask(task.getId(), transition);
							// 添加审批意见
							taskService.addTaskComment(task.getId(), ConstantUtil.SUBMIT_NAME);
						}
					}
				}
			}
		}
		return getNextOperatorsListByProcessInstanceId(processInstanceId);
	}

	public String getGroupIdByTaskId(String taskId) {

		if (null == taskId || "".equals(taskId)) {
			throw new JbpmException("通过任务标识获取组标识异常!");
		}

		String groupId = "";
		Session session = WorkflowFacade.getSession();
		try {
			TaskImpl task = (TaskImpl) session.get(TaskImpl.class, new Long(taskId));
			if (null != task) {
				Set participations = task.getParticipations();
				for (Iterator iter = participations.iterator(); iter.hasNext();) {
					Participation participation = (Participation) iter.next();
					groupId = participation.getGroupId();
					break;
				}
			}

		} catch (Exception e) {
			throw new JbpmException("通过任务标识获取组标识异常!" + e);
		} finally {
		}

		return groupId;

	}

	public String getNextOperatorsByTaskId(String taskId) {
		List userList = getNextOperatorsListByTaskId(taskId);
		return ReflectionUtils.convertElementPropertyToString(userList, "NAME", ",");
	}

	/**
	 * 
	 * 根据任务ID获取当前任务处理人
	 * 
	 * @param taskId
	 *            任务标识
	 * @return 当前任务处理人
	 */
	public List getNextOperatorsListByTaskId(String taskId) {
		List userList = new ArrayList();
		try {
			Criteria criteria = WorkflowFacade.getSession().createCriteria(TaskImpl.class);
			criteria.add(Restrictions.eq("dbid", new Long(taskId)));
			List tasks = criteria.list();
			for (Iterator iter = tasks.iterator(); iter.hasNext();) {
				TaskImpl task = (TaskImpl) iter.next();
				userList.addAll(getNextOperatorsByTaskImpl(task));
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("获取下一级处理人错误！");
		}
		return userList;

	}

	public String getNextOperatorsByProcessInstanceId(String processInstanceId) {
		List userList = getNextOperatorsListByProcessInstanceId(processInstanceId);
		return ReflectionUtils.convertElementPropertyToString(userList, "NAME", ",");
	}

	/**
	 * 
	 * 根据流程实例ID获取当前任务处理人
	 * 
	 * @param processInstanceId
	 *            流程实例ID
	 * @return 当前任务处理人
	 */
	public List getNextOperatorsListByProcessInstanceId(String processInstanceId) {
		List userList = new ArrayList();

		if (StringUtils.isNotEmpty(processInstanceId)) {
			Criteria criteria = WorkflowFacade.getSession().createCriteria(TaskImpl.class);
			criteria.add(Restrictions.eq("exeId", processInstanceId));
			List tasks = criteria.list();
			for (Iterator iter = tasks.iterator(); iter.hasNext();) {
				TaskImpl task = (TaskImpl) iter.next();
				userList.addAll(getNextOperatorsByTaskImpl(task));
			}
		}
		return userList;

	}

	/**
	 * 根据jbpm api TaskImpl对象获取当前处理人
	 * 
	 * @param task
	 *            当前任务对象
	 * @return 当前任务处理人
	 */
	private List getNextOperatorsByTaskImpl(TaskImpl task) {
		String nextOperatorCode = "";
		List userList = new ArrayList();
		String agencyId = "";
		String departmentId = "";
		Map conditions = new HashMap();

		if (null != task.getTaskType()) {
			conditions.put("conn", WorkflowFacade.getConnection());
			if (task.getTaskType().equals(ConstantUtil.COMMON_TASK) || task.getTaskType().equals(ConstantUtil.COUNTERSIGNATURE_TASK)) { // 普通任务
				nextOperatorCode = task.getAssignee();
				agencyId = task.getAgencyId();
				departmentId = task.getDepartmentId();
				conditions.put(ConstantUtil.AGENCY_ID, agencyId);
				conditions.put(ConstantUtil.DEPARTMENT_ID, departmentId);
				conditions.put("code", nextOperatorCode);
				conditions.put(ConstantUtil.SUBMIT_USER, task.getApplicationUser());
				userList = WorkflowQueryAdapter.getInstance().getUserListByCode(conditions);
			} else if (task.getTaskType().equals(ConstantUtil.COMMON_GROUP_TASK) || task.getTaskType().equals(ConstantUtil.DYNAMIC_TASK)) { // 普通组任务
				if (null != task.getAssignee()) {
					nextOperatorCode = task.getAssignee();
					agencyId = task.getAgencyId();
					departmentId = task.getDepartmentId();
					conditions.put(ConstantUtil.AGENCY_ID, agencyId);
					conditions.put(ConstantUtil.DEPARTMENT_ID, departmentId);
					conditions.put("code", nextOperatorCode);
					conditions.put(ConstantUtil.SUBMIT_USER, task.getApplicationUser());
					userList = WorkflowQueryAdapter.getInstance().getUserListByCode(conditions);
				} else {
					Set participations = task.getParticipations();
					String groupId = "";
					for (Iterator it = participations.iterator(); it.hasNext();) {
						ParticipationImpl part = (ParticipationImpl) it.next();
						if (task.getId().equals(part.getTask().getId())) {
							if (null != part.getGroupId()) {
								groupId = part.getGroupId();
								break;
							}
						}
					}
					agencyId = task.getAgencyId();
					departmentId = task.getDepartmentId();
					conditions.put(ConstantUtil.AGENCY_ID, agencyId);
					conditions.put(ConstantUtil.DEPARTMENT_ID, departmentId);
					conditions.put("groupId", groupId);
					conditions.put(ConstantUtil.SUBMIT_USER, task.getApplicationUser());
					userList = WorkflowQueryAdapter.getInstance().getUserListByGroupId(conditions);
				}
			}
		}
		return userList;
	}

	/**
	 * 
	 * 根据流程实例ID获取任务节点名称
	 * 
	 * @param processInstanceId
	 * @return 任务节点名称
	 */
	public String getActivityNameByProcessInstanceId(String processInstanceId) {

		String activityName = "";
		try {
			if (null != processInstanceId && !"".equals(processInstanceId)) {
				Criteria criteria = WorkflowFacade.getSession().createCriteria(TaskImpl.class);
				ProjectionList projectionList = Projections.projectionList();
				projectionList.add(Projections.property("activityName").as("activityName"));
				criteria.setProjection(projectionList);
				criteria.createAlias("processInstance", "processInstance");
				criteria.add(Restrictions.eq("processInstance.id", processInstanceId));
				criteria.add(Restrictions.ne("state", "suspended"));
				criteria.add(Restrictions.ne("taskType", ConstantUtil.COUNTERSIGNATURE_TASK));

				List taskList = criteria.list();

				activityName = StringUtils.join(taskList.toArray(), ",");
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("获取任务节点名称错误！");
		}
		return activityName;

	}

	/**
	 * 获取流程历史信息
	 * 
	 * @param taskId
	 *            任务标识
	 * @param conn
	 *            数据库连接
	 * @return 流程历史信息列表，列表元素是: 任务处理人，代理人，处理时间，意见类型，意见内容。 返回的List形式为:
	 *         List&ltMap&ltString, Object&gt&gt
	 */
	public List getProcessHistoryInfosByTaskId(String taskId) {
		if (null == taskId || "".equals(taskId)) {
			throw new JbpmException("无效的任务标识!");
		}
		String processInstanceId = "";
		TaskImpl task = (TaskImpl) taskService.getTask(taskId);
		if (null == task) {
			HistoryTaskImpl historyTask = (HistoryTaskImpl) WorkflowFacade.getSession().get(HistoryTaskImpl.class, new Long(taskId));
			processInstanceId = historyTask.getExeId();
		} else {
			processInstanceId = task.getExeId();
		}
		return getProcessHistoryInfosByProcessInstanceId(processInstanceId);
	}

	public List getProcessHistoryInfosByTaskId(String taskId, boolean isNeedSubmitActivity) {
		if (null == taskId || "".equals(taskId)) {
			throw new JbpmException("无效的任务标识!");
		}
		String processInstanceId = "";
		TaskImpl task = (TaskImpl) taskService.getTask(taskId);
		if (null == task) {
			HistoryTaskImpl historyTask = (HistoryTaskImpl) WorkflowFacade.getSession().get(HistoryTaskImpl.class, new Long(taskId));
			processInstanceId = historyTask.getExeId();
		} else {
			processInstanceId = task.getExeId();
		}
		return getProcessHistoryInfosByProcessInstanceId(processInstanceId, isNeedSubmitActivity);
	}

	/**
	 * 根据流程实例ID获取历史流程信息
	 * 
	 * @param processInstanceId
	 *            流程实例ID
	 * @return 历史流程信息
	 */
	public List getProcessHistoryInfosByProcessInstanceId(String processInstanceId) {
		if (null == processInstanceId || "".equals(processInstanceId)) {
			throw new JbpmException("无效的流程实例标识!");
		}

		Criteria criteria = WorkflowFacade.getSession().createCriteria(HistoryTaskImpl.class);
		criteria.createAlias("details", "details");

		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(Projections.property("assignee").as("assignee"));
		projectionList.add(Projections.property("agentId").as("agentId"));
		projectionList.add(Projections.property("name").as("activityName"));
		projectionList.add(Projections.property("businessRecordId").as("businessRecordId"));
		projectionList.add(Projections.property("businessType").as("businessType"));
		projectionList.add(Projections.property("businessName").as("businessName"));
		projectionList.add(Projections.property("businessSN").as("businessSN"));
		projectionList.add(Projections.property("endTime").as("endTime"));
		projectionList.add(Projections.property("details.message").as("message"));
		projectionList.add(Projections.property("agencyId").as("agencyId"));
		projectionList.add(Projections.property("departmentId").as("departmentId"));
		criteria.setProjection(projectionList);

		criteria.add(Restrictions.eq("state", "completed"));
		criteria.add(Restrictions.isNull("abnormal"));
		criteria.add(Restrictions.eq("exeId", processInstanceId));

		criteria.addOrder(Order.asc("endTime"));
		criteria.setResultTransformer(Transformers.aliasToBean(ProcessHistoryInfo.class));
		List historyTasks = criteria.list();

		return historyTasks;
	}

	public List getProcessHistoryInfosByProcessInstanceId(String processInstanceId, boolean isNeedSubmitActivity) {
		if (null == processInstanceId || "".equals(processInstanceId)) {
			throw new JbpmException("无效的流程实例标识!");
		}

		Criteria criteria = WorkflowFacade.getSession().createCriteria(HistoryTaskImpl.class);
		criteria.createAlias("details", "details");

		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(Projections.property("assignee").as("assignee"));
		projectionList.add(Projections.property("agentId").as("agentId"));
		projectionList.add(Projections.property("name").as("activityName"));
		projectionList.add(Projections.property("businessRecordId").as("businessRecordId"));
		projectionList.add(Projections.property("businessType").as("businessType"));
		projectionList.add(Projections.property("businessName").as("businessName"));
		projectionList.add(Projections.property("businessSN").as("businessSN"));
		projectionList.add(Projections.property("endTime").as("endTime"));
		projectionList.add(Projections.property("details.message").as("message"));
		projectionList.add(Projections.property("agencyId").as("agencyId"));
		projectionList.add(Projections.property("departmentId").as("departmentId"));
		criteria.setProjection(projectionList);

		criteria.add(Restrictions.eq("state", "completed"));
		criteria.add(Restrictions.isNull("abnormal"));
		criteria.add(Restrictions.eq("exeId", processInstanceId));
		if (!isNeedSubmitActivity) {
			Disjunction disjunction = Restrictions.disjunction();
			disjunction.add(Restrictions.isNull("submitActivity"));
			disjunction.add(Restrictions.ne("submitActivity", "submitActivity"));
			criteria.add(disjunction);
		}
		criteria.addOrder(Order.asc("endTime"));
		criteria.setResultTransformer(Transformers.aliasToBean(ProcessHistoryInfo.class));
		List historyTasks = criteria.list();

		return historyTasks;
	}

	/**
	 * 获取审批时流程所走的流向
	 * 
	 * @param taskId
	 *            任务标识
	 * @param approveType审批类型
	 * @return 任务的流向
	 */
	public String getTaskTransition(String taskId, String approveType) {

		String transition = "";
		try {
			if (null != taskId && !"".equals(taskId) && null != approveType && !"".equals(approveType)) {
				TaskImpl task = (TaskImpl) taskService.getTask(taskId);

				if (ConstantUtil.COUNTERSIGNATURE_TASK.equals(task.getTaskType())) { // 会签任务
					if ("true".equals(approveType)) { // 会签节点且同意审批
						List list = new ArrayList(taskService.getOutcomes(task.getSuperTask().getId()));
						if (null != list) {
							transition = (String) list.get(0);
							return transition;
						}
					}
				}

				List transitions = taskService.getOutcomesDup(taskId);
				if (null == transitions) {
					transitions = taskService.getOutcomesDup(task.getSuperTask().getId());
				}
				for (Iterator iter = transitions.iterator(); iter.hasNext();) {
					TransitionImpl transitionImpl = (TransitionImpl) iter.next();
					if (approveType.equals(transitionImpl.getPass().toLowerCase()) && !ConstantUtil.SUBMIT_SECOND.equals(transitionImpl.getActivityName())) {
						transition = transitionImpl.getName();
						break;
					}
				}

			}
			if (StringUtils.isEmpty(transition)) {
				throw new JbpmException("无法获取任务流向");
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("获取任务流向错误！");
		}
		return transition;
	}



	private String getPropertyValueByActivity(String key, ActivityImpl destination) {
		String text = "";
		ProcessDefinitionImpl processDefinition = destination.getProcessDefinition();
		TaskDefinitionImpl taskDefinition = processDefinition.getTaskDefinition(destination.getName());
		if (taskDefinition != null) {
			UserCodeReference userCodeReference = taskDefinition.getAssignmentHandlerReference();
			if (null != userCodeReference) {
				ObjectDescriptor descriptor = (ObjectDescriptor) userCodeReference.getDescriptor();
				List list = descriptor.getOperations();
				for (Iterator it = list.iterator(); it.hasNext();) {
					FieldOperation op = (FieldOperation) it.next();
					String filedName = op.getFieldName();
					if (key.equals(filedName)) {
						StringDescriptor stringDescriptor = (StringDescriptor) op.getDescriptor();
						text = (String) stringDescriptor.construct((WireContext) environmentFactory.get("wire-context"));
						break;
					}
				}
			}
		}
		return text;
	}

	public boolean isEndedByProcessDefine(String taskId) {
		List outgoingTransitions = getOutgoingTransitionsByTaskId(taskId);
		for (Iterator it = outgoingTransitions.iterator(); it.hasNext();) {
			TransitionImpl transitionImpl = (TransitionImpl) it.next();
			ActivityImpl destination = transitionImpl.getDestination();
			String type = destination.getType();
			if (type.equals("end")) {
				return true;
			}
		}
		return false;
	}

	public String getEndTransitionByTaskId(String taskId) {
		List outgoingTransitions = getOutgoingTransitionsByTaskId(taskId);
		for (Iterator it = outgoingTransitions.iterator(); it.hasNext();) {
			TransitionImpl transitionImpl = (TransitionImpl) it.next();
			ActivityImpl destination = transitionImpl.getDestination();
			String type = destination.getType();
			if (type.equals("end") || type.equals("fork") || type.equals("join") || type.equals("decision") || type.equals("countersign-node")
					|| type.equals("foreach")) {
				return transitionImpl.getName();
			}
		}
		return "";
	}

	public String getTaskTransitionByActivityName(String taskId) {

		String transition = "";
		try {
			if (null != taskId && !"".equals(taskId)) {

				List transitions = taskService.getOutcomesDup(taskId);

				for (Iterator iter = transitions.iterator(); iter.hasNext();) {
					TransitionImpl transitionImpl = (TransitionImpl) iter.next();
					if (ConstantUtil.SUBMIT_SECOND.equals(transitionImpl.getActivityName())) {
						transition = transitionImpl.getName();
						break;
					}
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new JbpmException("获取任务流向错误！");
		}
		return transition;
	}

	public String getProcessDefinitionByProcessInstanceId(String processInstanceId) {
		StringBuffer stringBuffer = new StringBuffer();
		if (null != processInstanceId && !"".equals(processInstanceId)) {
			String processDefinitionId = historyService.createHistoryProcessInstanceQuery().processInstanceId(processInstanceId).uniqueResult()
					.getProcessDefinitionId();

			String deploymentId = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).uniqueResult().getDeploymentId();
			Session session = WorkflowFacade.getSession();

			try {
				String sql = "select lob.blob_value_ from " + TableConstants.JBPM4_LOB + " lob where lob.deployment_ = '" + deploymentId + "'";
				Connection conn = session.connection();
				PreparedStatement ps = conn.prepareStatement(sql);
				ResultSet rs = ps.executeQuery();
				Blob blob = null;
				if (rs.next()) {
					blob = rs.getBlob(1);
				}
				if (null != blob) {
					InputStream is = blob.getBinaryStream();
					byte[] buffer = new byte[4096];
					int temp = -1;
					while ((temp = is.read(buffer)) != -1) {
						stringBuffer.append(new String(buffer, 0, temp, "UTF-8"));
					}
				}
			} catch (Exception e) {
				throw new JbpmException("通过流程实例标识 获取流程定义内容时异常!" + e);
			} finally {

			}

		}

		return stringBuffer.toString();
	}
	public String getAssignRuleByProcessDefine(String taskId, String key) {
		List outgoingTransitions = getOutgoingTransitionsByTaskId(taskId);
		TransitionImpl transitionImpl = null;
		for (int i = 0; i < outgoingTransitions.size(); i++) {
			TransitionImpl t = (TransitionImpl) outgoingTransitions.get(i);
			if ("true".equals(t.getPass())){
				transitionImpl = t;
				break;
			}
		}
		if (transitionImpl == null)
			return null;
		ActivityImpl destination = transitionImpl.getDestination();
		String type = destination.getType();
		if ("foreach".equals(type) || "join".equals(type)) {
			outgoingTransitions = destination.getOutgoingTransitions();
			transitionImpl = (TransitionImpl) outgoingTransitions.get(0);
			destination = transitionImpl.getDestination();
			return getPropertyValueByActivity(key, destination);
		} else if ("task".equals(type)) {
			return getPropertyValueByActivity(key, destination);
		}
		return null;
	}
}
